package com.bbx.demo.grpc.client;

import com.bbx.demo.grpc.generated.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import java.util.Iterator;

@Slf4j
public class GrpcClient {

    public static void main(String[] args) {
        ManagedChannel build = ManagedChannelBuilder.forAddress("192.168.2.252", 8099).usePlaintext().build();
        //Creates a new blocking-style stub that supports unary and streaming output calls on the service   只能用于普通的请求响应和 普通请求 ，流式响应
        RouteGuideGrpc.RouteGuideBlockingStub routeGuideBlockingStub = RouteGuideGrpc.newBlockingStub(build);
        //Creates a new async stub that supports all call types for the service      能处理全部的请求和响应
        RouteGuideGrpc.RouteGuideStub routeGuideStub = RouteGuideGrpc.newStub(build);

        // 普通请求 普通响应
        testGetFeature(routeGuideBlockingStub);
        //普通请求 流式响应
        testListFeatures(routeGuideBlockingStub);
        //流式请求 普通响应
        testRecordRoute(routeGuideStub);
        //流式请求 流式响应
        testRouteChat(routeGuideStub);

    }

    /**
     * 普通请求 普通响应
     *
     * @param routeGuideBlockingStub
     */
    public static void testGetFeature(RouteGuideGrpc.RouteGuideBlockingStub routeGuideBlockingStub) {
        Feature feature = routeGuideBlockingStub.getFeature(Point.newBuilder().setLongitude(123).setLatitude(456).build());
        log.info("普通请求 普通响应~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        log.info("Latitude[{}],Longitude[{}]", feature.getLocation().getLatitude(), feature.getLocation().getLongitude());
        log.info("Name[{}]", feature.getName());
    }

    /**
     * 普通请求 流式响应
     *
     * @param routeGuideBlockingStub
     */
    public static void testListFeatures(RouteGuideGrpc.RouteGuideBlockingStub routeGuideBlockingStub) {
        Iterator<Feature> featureIterator = routeGuideBlockingStub.listFeatures(Rectangle.newBuilder()
                .setHi(Point.newBuilder().setLongitude(1).setLatitude(2).build())
                .setLo(Point.newBuilder().setLatitude(3).setLongitude(4).build())
                .build());

        while (featureIterator.hasNext()) {
            Feature next = featureIterator.next();
            log.info("普通请求 流式响应~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            log.info("Name[{}]", next.getName());
            log.info("Longitude[{}],Longitude[{}]", next.getLocation().getLongitude(), next.getLocation().getLongitude());
        }
    }


    /**
     * 流式请求 普通响应
     *
     * @param routeGuideStub
     */
    public static void testRecordRoute(RouteGuideGrpc.RouteGuideStub routeGuideStub) {
        StreamObserver<RouteSummary> streamObserver = new StreamObserver<RouteSummary>() {
            @Override
            public void onNext(RouteSummary value) {
                log.info("流式请求 普通响应~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                log.info("Distance[{}],ElapsedTime[{}],FeatureCount[{}],PointCount[{}]", value.getDistance(), value.getElapsedTime(), value.getFeatureCount(), value.getPointCount());
            }

            @Override
            public void onError(Throwable t) {
                log.error("error", t);
            }

            @Override
            public void onCompleted() {
            }
        };
        StreamObserver<Point> pointStreamObserver = routeGuideStub.recordRoute(streamObserver);
        for (int i = 10; i < 15; i++) {
            pointStreamObserver.onNext(Point.newBuilder().setLatitude(i).setLongitude(i).build());
            try {
                //为了便于观察，无实际意义
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        pointStreamObserver.onCompleted();
        try {
            //等待响应
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    /**
     * 流式请求 流式响应
     *
     * @param routeGuideStub
     */
    public static void testRouteChat(RouteGuideGrpc.RouteGuideStub routeGuideStub) {
        StreamObserver<RouteNote> streamObserver = new StreamObserver<RouteNote>() {
            @Override
            public void onNext(RouteNote value) {
                log.info("流式请求 流式响应~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                log.info("Message[{}],Latitude[{{}],Longitude[{}]", value.getMessage(), value.getLocation().getLatitude(), value.getLocation().getLongitude());
            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onCompleted() {
                log.info("传输完成 ，关闭");
            }
        };
        StreamObserver<RouteNote> routeNoteStreamObserver = routeGuideStub.routeChat(streamObserver);
        for (int i = 15; i < 20; i++) {
            routeNoteStreamObserver.onNext(RouteNote.newBuilder().setLocation(Point.newBuilder().setLongitude(i).setLatitude(i).build()).build());
        }
        routeNoteStreamObserver.onCompleted();
        try {
            //等待响应
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


}
